
#include "../common/cluster.h"
#include "../common/mem.h"

/*  This is the main function that handles partitioning of a network into clusters. */
/*  The function returns the partitions created by the algorithms. */
partitions* partition_cluster(sparse_matrix_arr* adj_matrix, elem precision, double* Que)
{
	partitions* P;
	partition_group* g;
	int g1Count, g2Count;
	int* g1;
	int* g2;
	double deltaQue;
	int isDivisible;

	/*  Initialize */
	*Que = 0;
	deltaQue = 0;

	/* Make partitions data structure from the adjacency matrix */
	P = init_partitions(adj_matrix);

	/*  Start processing divisible groups */
	g = pop_next_divisible(P);

	/*  While there are divisible groups in P */
	while (g != 0)
	{
		debug_output("Popped group: id=%i, size=%i. doing Spectral.\n", g->id, g->size);

		deltaQue = 0;

		/*  Try dividing the currently selected group */
		spectralDiv(adj_matrix, precision, g->indices, g->size, &deltaQue, 
			&g1, &g2, &g1Count, &g2Count, USE_IMPROVE_DIV);

		debug_output("spectral done.\n");
		
		/*  No success dividing? */
		if ((g1Count == 0) || (g2Count == 0))
		{
			/* Mark the group as indivisible */
			set_divisiblity(P, g, INDIVISABLE);

			/* Deallocate indices arrays */
			mem_free(g1);
			mem_free(g2);
		} 
		else /*  Successful division? */
		{
			/* Add the modularity change to the total modularity score */
			*Que += deltaQue;

			/*  add g1 (group 1) to the partitions */
			isDivisible = (g1Count == 1) ? INDIVISABLE : DIVISIBLE;
			add_to_partitions(P, g1, isDivisible, g1Count);
			
			/*  add g2 (group 2) to the partitions */
			isDivisible = (g2Count == 1) ? INDIVISABLE : DIVISIBLE;
			add_to_partitions(P, g2, isDivisible, g2Count);
		}
		
		/*  Get next divisible group (g == 0 if no more divisible groups)*/
		g = pop_next_divisible(P);
	}

	return P;
}
